package com.funny.stock.trade.service;

import com.funny.stock.base.service.BaseCrudServiceV2;
import com.funny.stock.base.util.PageUtil;
import com.funny.stock.base.util.PropertiesCopyUtil;
import com.funny.stock.base.util.ResultUtil;
import com.funny.stock.base.vo.Result;
import com.funny.stock.base.vo.TradeType;
import com.funny.stock.data.collect.StockPoolService;
import com.funny.stock.data.dao.entity.StockDO;
import com.funny.stock.data.service.StockService;
import com.funny.stock.data.vo.Stock;
import com.funny.stock.data.vo.StockConstants;
import com.funny.stock.trade.dao.pojo.ComposeStockActionDO;
import com.funny.stock.trade.dao.pojo.DayTradeProfitDO;
import com.funny.stock.trade.dao.repo.ComposeStockActionRepo;
import com.funny.stock.trade.vo.ComposeStockActionQueryVO;
import com.funny.stock.trade.vo.ComposeStockActionVO;
import com.funny.stock.trade.vo.EmulateComposeVO;
import com.funny.stock.trade.vo.TradeActionInfo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.Predicate;

/**
 * @Description  
 * @Author  pengl
 * @Date 2020-05-17 
 */

@Service
public class ComposeStockActionService extends BaseCrudServiceV2<ComposeStockActionVO,ComposeStockActionDO,Long> {
	private static final Logger logger = LoggerFactory.getLogger(ComposeStockActionService.class);

	@Autowired
	ComposeStockActionRepo repository;

	@Autowired
	EmulateComposeService emulateComposeService;

	@Autowired
	ComposeStockItemService composeStockItemService;

	@Autowired
	ComposeStockItemService stockItemService;

	@Autowired
	ComposeStockActionService selfService;

	@Autowired
	DayTradeRecordService dayTradeRecordService;

	@Autowired
	StockPoolService stockPoolService;

	@Autowired
	StockService stockService;

	protected JpaRepository<ComposeStockActionDO, Long> setupJpaRepository() {
		return repository;
	}

	@Override
	protected Class<ComposeStockActionDO> getDOClass() {
		return ComposeStockActionDO.class;
	}

	@Override
	protected Class<ComposeStockActionVO> getVOClass() {
		return ComposeStockActionVO.class;
	}

	@Transactional
	public Result<DayTradeProfitDO> doTradeActionByMonitor(TradeActionInfo tradeActionInfo){
		EmulateComposeVO composeVO = emulateComposeService.findByCreateIdAndId(tradeActionInfo.getPersonId(), tradeActionInfo.getComposeId());
		if(composeVO == null){
			logger.info("交易触发执行失败，组合不存在:{}",tradeActionInfo.getCode());
			return ResultUtil.error("交易触发执行失败，组合不存在");
		}

		ComposeStockActionVO actionVO = new ComposeStockActionVO();
		actionVO.setComposeId(tradeActionInfo.getComposeId());
		actionVO.setAction(tradeActionInfo.getTradeType().getType());
		actionVO.setActionNumber(tradeActionInfo.getTradeNumber());
		actionVO.setActionPrice(BigDecimal.valueOf(tradeActionInfo.getRealtimeStockData().getPrice()));
		actionVO.setStockCode(tradeActionInfo.getRealtimeStockData().getSymbol());
		actionVO.setStockName(tradeActionInfo.getRealtimeStockData().getName());
		actionVO.setTotalMoney(actionVO.getActionPrice().multiply(BigDecimal.valueOf(actionVO.getActionNumber())));
		actionVO.setCreateId(tradeActionInfo.getPersonId());
		actionVO.setCreateTime(new Date());
		actionVO.setIsDelete(0);
		actionVO.setRemark(tradeActionInfo.getPlanType());

		Result<ComposeStockActionVO> result = selfService.doTradeAction(tradeActionInfo.getPersonId(),actionVO,composeVO);
		if(result.getCode() == ResultUtil.CODE_SUCCESS){
			logger.info("交易触发执行成功:{},{}",tradeActionInfo.getCode(),tradeActionInfo.getTradeType().getType());
			return ResultUtil.success(dayTradeRecordService.doTradeAction(tradeActionInfo));
		}
		return ResultUtil.error(result.getMsg());
	}

	@Transactional
	public Result<ComposeStockActionVO> doTradeAction(Long userInfoId, ComposeStockActionVO actionVO, EmulateComposeVO assetsVO){
		if(actionVO.getAction() == TradeType.BUY.getType() && !emulateComposeService.canBuy(assetsVO,
				actionVO.getActionPrice(), actionVO.getActionNumber())){
			return ResultUtil.error(StockConstants.PRICE_NOT_ENOUGH_CODE,"执行交易失败,买入现金不足");
		}

		StockDO stockDO = stockService.findByCode(actionVO.getStockCode());
		if(stockDO == null){
			return ResultUtil.error("执行交易失败,系统暂无该股票信息,请联系管理员");
		}

		actionVO.setStockMarket(stockDO.getMarket());
		ComposeStockActionDO stockActionDO = convertDO(actionVO);
		stockActionDO.setCreateId(userInfoId);
		stockActionDO.setCreateTime(new Date());

		//更新资产
		BigDecimal totalMoney = stockActionDO.getActionPrice().multiply(BigDecimal.valueOf(stockActionDO.getActionNumber()));
		if(actionVO.getAction() == TradeType.BUY.getType()){
//			assetsVO.setCapital(assetsVO.getCapital().add(totalMoney));
			assetsVO.setCash(assetsVO.getCash().subtract(totalMoney));
		}else{
//			assetsVO.setCapital(assetsVO.getCapital().subtract(totalMoney));
			assetsVO.setCash(assetsVO.getCash().add(totalMoney));
		}
		stockActionDO.setTotalMoney(totalMoney);

		assetsVO.setBalance(assetsVO.getCapital().add(assetsVO.getCash()));
		assetsVO.setUpdateId(userInfoId);
		assetsVO.setUpdateTime(new Date());

		//先执行组合内股票的添加操作
		Result stockItemDOResult = composeStockItemService.doTradeStock(userInfoId, stockActionDO);
		if(stockItemDOResult.getCode() != ResultUtil.CODE_SUCCESS){
			return stockItemDOResult;
		}

		//再更新组合现金信息
		emulateComposeService.save(assetsVO);
		composeStockItemService.removeComposeAssetCache(stockActionDO.getCreateId(),stockActionDO.getComposeId());

		//添加股票到股票池
		Stock stock = PropertiesCopyUtil.copyProperties(stockDO, Stock.class);
		stockPoolService.addStock(stock);

		//保存交易记录
		ComposeStockActionDO save = repository.save(stockActionDO);
		ComposeStockActionVO vo = convertVO(save);
		return ResultUtil.success(vo);
	}


	public Page<ComposeStockActionVO> queryByCondition(ComposeStockActionQueryVO queryVO){
		Specification specification = (Specification) (root, criteriaQuery, criteriaBuilder) -> {
			List<Predicate> predicates = new ArrayList<>();

			if(!StringUtils.isEmpty(queryVO.getCode())) {
				predicates.add(criteriaBuilder
						.equal(root.get("stockCode"), queryVO.getCode()));
			}

			if(null != queryVO.getCreateId()){
				predicates.add(criteriaBuilder.equal(root.get("createId"), queryVO.getCreateId()));
			}

			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			if(null != queryVO.getStartDate()){
				try {
					Date startDate = dateFormat.parse(queryVO.getStartDate());
					predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), startDate));
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}

			if(null != queryVO.getEndDate()){
				try {
					Date endDate = dateFormat.parse(queryVO.getEndDate());
					predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime"), endDate));
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}

			return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
		};
		PageRequest pageRequest = PageUtil.buildPageRequest(queryVO.getPageNumber(), queryVO.getPageSize());
		return repository.findAll(specification,pageRequest);
	}

}
